package jp.tkym.labs.family.client;

import org.vaadin.gwtgraphics.client.DrawingArea;
import org.vaadin.gwtgraphics.client.Group;
import org.vaadin.gwtgraphics.client.shape.Rectangle;
import org.vaadin.gwtgraphics.client.shape.Text;

import com.google.gwt.animation.client.Animation;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Family implements EntryPoint {
	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private static final String SERVER_ERROR = 
			"An error occurred while "
			+ "attempting to contact the server. Please check your network "
			+ "connection and try again.";

	/**
	 * Create a remote service proxy to talk to the server-side Greeting service.
	 */
	private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
	
	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		DrawingArea canvas = new DrawingArea(800, 400);
		
		PersonCard jun = new PersonCard(person("Junichi", "Takayama", Person.Gender.MALE));
		PersonCard yuk = new PersonCard(person("Yukie", "Takayama", Person.Gender.FEMALE));
		
		canvas.add(jun.card().eraser());
		canvas.add(yuk.card().eraser());
		canvas.add(jun.card().group());
		canvas.add(yuk.card().group());
		
		jun.card().move(100, 10);
		yuk.card().move(300, 10);
		
		RootPanel.get("rootContainer").add(canvas);
	}
	
	Person person(String firstName, String familyName, Person.Gender gender){
		Person person = new Person();
		person.setFamilyName(familyName);
		person.setFirstName(firstName);
		person.setGender(gender);
		return person;
	}
	
	
	
	
	
	
	class MovingCard{
		int width = 150;
		int height = 20;
		int fontSize = 14;
		int roundSize = 3;
		int speed = 1000;
		String forwordColor = "red";
		String backColor = "white";
		private MoveText text;
		private MoveRectangle rect;
		private Group group;
		private MoveAnimation textMove;
		private MoveAnimation rectMove;
		
		MovingCard(int x, int y, String name, String color){
			this.text = textbox(x, y, name);
			this.rect = rect(x, y, color);
			this.group = new Group();
			this.textMove = new MoveAnimation(this.text, speed);
			this.rectMove = new MoveAnimation(this.rect, speed);
			this.rectMove.eraser.setFillColor(backColor);
			this.rectMove.eraser.setStrokeWidth(2);
			this.rectMove.eraser.setStrokeColor(backColor);
			this.group.add(this.rect);
			this.group.add(this.text);
		}
		
		Rectangle eraser(){
			return this.rectMove.eraser;
		}
		
		void setPosition(int x, int y){
			text.setX(x+roundSize);
			text.setY(y+fontSize);
			rect.setX(x);
			rect.setY(y);
		}
		
		MoveText textbox(int x, int y, String name){
			MoveText textbox = new MoveText(x+roundSize, y+fontSize, name);
			textbox.setFillColor(backColor);
			textbox.setStrokeWidth(0);
			textbox.setFontSize(fontSize);
			return textbox;
		}
		
		MoveRectangle rect(int x, int y, String color){
			MoveRectangle rect = new MoveRectangle(x, y, width, height);
			rect.setFillColor(color);
			rect.setRoundedCorners(roundSize);
			rect.setStrokeWidth(0);
			rect.setStrokeColor(color);
			return rect;
		}
		
		void move(int x, int y){
			this.rectMove.move(x, y);
			this.textMove.move(x+roundSize, y+fontSize);
		}
		
		Group group(){
			return group;
		}
	}
	
	class MoveRectangle extends Rectangle implements ClearMoveAnimatable{
		public MoveRectangle(int x, int y, int width, int height) {
			super(x, y, width, height);
		}
	}
	
	class MoveText extends Text implements MoveAnimatable{
		public MoveText(int x, int y, String text) {
			super(x, y, text);
		}
	}
	
	interface ClearMoveAnimatable extends MoveAnimatable{
		public int getWidth();
		public int getHeight();
	}
	
	interface MoveAnimatable{
		public void setX(int x);
		public void setY(int y); 
		public int getX();
		public int getY();
	}
	
	class MoveAnimation{
		private int duration;
		private MoveAnimatable target;
		private Rectangle eraser;
		
		MoveAnimation(MoveAnimatable target, int duration){
			this.target = target;
			this.duration = duration;
			if(target instanceof ClearMoveAnimatable){
				ClearMoveAnimatable erasable = (ClearMoveAnimatable) target; 
				eraser = new Rectangle(
						erasable.getX(), 
						erasable.getY(), 
						erasable.getWidth(), 
						erasable.getHeight());
			}
			else{
				eraser = null;
			}
		}
		
		void move(int x, int y){
			final int sx = target.getX();
			final int sy = target.getY();
			final int ex = x;
			final int ey = y;
			final int dx = ex - sx;
			final int dy = ey - sy;
			Animation animation = new Animation() {
				@Override
				protected void onUpdate(double progress) {
					if(eraser != null){
						eraser.setX(target.getX());
						eraser.setY(target.getY());
					}
					target.setX((int)(sx + dx * progress));
					target.setY((int)(sy + dy * progress));
				}
			};
			animation.run(this.duration);
		}
	}
	
	class PersonCard{
		private Person person;
		private MovingCard card; 
		
		PersonCard(Person person){
			this.person = person;
			String color;
			if(person.getGender().equals(Person.Gender.MALE))
				color = "blue";
			else
				color = "red";
			String name = person.getFirstName() + " " + person.getFamilyName();
			this.card = new MovingCard(0, 0, name, color);
		}
		
		MovingCard card(){
			return card;
		}
	}
}